package com.filldream.fastboot.web.config.request;

import com.alibaba.fastjson2.JSONObject;
import com.filldream.fastboot.common.annotation.PassTokenAnnotation;
import com.filldream.fastboot.common.annotation.RolePermissions;
import com.filldream.fastboot.common.constant.FinalStr;
import com.filldream.fastboot.common.entity.RequestDTO;
import com.filldream.fastboot.common.util.RequestContext;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.ObjectUtils;
import org.springframework.util.PathMatcher;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.*;

/**
 * 请求校验辅助工具
 * @author RickSun && iFillDream
 * @version 1.0
 * @data 2020-10-23 17:06
 * @updata 2023-12-08 12:54
 */
@Slf4j
public class RequestUtil {

    /**
     * 获取日志类
     * @param request   javax.servlet.http.HttpServletRequest
     * @param method    java.lang.reflect.Method
     * @return  RequestDTO
     * @see RequestDTO
     */
    public static RequestDTO getRequestLog(HttpServletRequest request,Method method){
        if( request == null ){
            log.info("GetRequestLog异常：{}","HttpServletRequest为空");
        }
        RequestDTO logResult = new RequestDTO();
        logResult.setMethodType( request.getMethod() );
        String queryString = request.getQueryString();
        logResult.setQueryParam( queryString == null ? "" : queryString );
        logResult.setParameterMap(request.getParameterMap());
        logResult.setIp( RequestContext.getIp2() );
        logResult.setUri( request.getRequestURI() );
        logResult.setUrl( request.getRequestURL().toString() );
        logResult.setHeadMap( getHeadMap(request,Arrays.asList( "token","content-type", FinalStr.passToken,"TOKEN","Token" )) );
        logResult.setBody( getBody(request) );
        logResult.setTitle( method != null ? getApiTitle(method) : "");
        return logResult;
    }

    /**
     * 获取指定请求头
     * @param request
     * @param showNameList
     * @return
     */
    public static Map<String,Object> getHeadMap(HttpServletRequest request,List<String> showNameList){
        Enumeration<String> headerNames = request.getHeaderNames();
        Map<String,Object> headMap = new HashMap<>();
        if(!ObjectUtils.isEmpty(headerNames)){
            while (headerNames.hasMoreElements()){
                String name = headerNames.nextElement();
                if( showNameList.contains(name) ){
                    headMap.put( name, request.getHeader(name));
                }
            }
        }
        return headMap;
    }

    /**
     * 获取请求流数据
     * @param request
     * @return
     */
    public static String getBody(HttpServletRequest request){
        //request.getContentType()可能为null，注意equal()的顺序
        String contentType = request.getContentType();
        //如果是post请求的json,需特别处理
        if( MediaType.APPLICATION_JSON_VALUE.equals(contentType) || MediaType.APPLICATION_JSON_UTF8_VALUE.equals(contentType) ){
            try {
                String bodyString = new RequestWrapper(request).getBodyString();
                //传参是什么样子，bodyString就是什么样子，包含了换行符空格之类的，这里需要转换一下
                return JSONObject.parseObject(bodyString).toString();
            } catch (IOException e) {
                log.info( "RequestUtil-GetBody异常:{}",e.getMessage() );
            }
        }
        return "";
    }

    /**
     * @author RickSun
     * @Description 请求路径校验 待验证
     * @param uri 请求uri
     * @param pathPatterns  需校验的规则
     * @param excludePathPatterns   不校验类型
     * @return boolean 是否需要拦截处理 true-需拦截处理 false-不需要拦截，直接通过
     **/
    public static boolean checkUri( String uri,String[] pathPatterns,String[]  excludePathPatterns){
        PathMatcher matcher = new AntPathMatcher();
        boolean result = true;
        if( ObjectUtils.isEmpty(pathPatterns) ){
            return false;
        }
        if( ObjectUtils.isEmpty(uri) ){
            return true;
        }

        //筛选排除
        for (String excludePathPattern : excludePathPatterns) {
            if(matcher.match( excludePathPattern,uri )){
                return false;
            }
        }

        //校验
        for (String pathPattern : pathPatterns) {
            result = matcher.match( pathPattern,uri );
            if(result){
                return result;
            }
        }
        return result;
    }

    /**
     * 获取PassToken注解
     * @param method    Method
     * @param isPass    是否开启PassToken校验，true的时候才会获取注解，false直接返回null
     * @return
     */
    public static PassTokenAnnotation getPassTokenAnnotation( Method method,boolean isPass ){
        if( isPass ){
            // 判断请求passToken是否存在
            PassTokenAnnotation passTokenAnnotation = method.getAnnotation(PassTokenAnnotation.class);
            if (org.apache.commons.lang3.ObjectUtils.isEmpty(passTokenAnnotation)) {
                // 如果被PassTokenAnnotation注解的代表此类所有方法必须传入passToken
                passTokenAnnotation = method.getDeclaringClass().getAnnotation(PassTokenAnnotation.class);
            }
            return  passTokenAnnotation;
        }
        return  null;
    }

    /**
     * 获取权限注解
     * @param method
     * @return
     */
    public static RolePermissions getRolePermissionsAnnotation(Method method) {
        RolePermissions rolePermissions = null;
        //如果被RolePermissions注解代表需要鉴权，通常用于PC端
        rolePermissions = method.getAnnotation(RolePermissions.class);
        if (ObjectUtils.isEmpty(rolePermissions)) {
            rolePermissions = method.getDeclaringClass().getAnnotation(RolePermissions.class);
        }
        return rolePermissions;
    }

    /**
     * 获取Swagger接口名称
     * @param method
     * @return
     */
    public static String getApiTitle(Method method) {
        ApiOperation apiAnnotation = method.getAnnotation(ApiOperation.class);
        if( apiAnnotation != null ){
            return apiAnnotation.value();
        }
        return "";
    }

}
